﻿using Entity = Vinno.Brand.Pack.Core.Entities.ProductCase;
using InputDto = Vinno.Brand.Pack.Core.Dtos.ProductCaseInputDto;

namespace Vinno.Brand.Pack.Core.Stores
{
    /// <summary>
    /// 品牌空间信息存储
    /// </summary>
    [Dependency(ServiceLifetime.Scoped)]
    public class ProductCaseStore
    {
        /// <summary>
        /// 初始化一个存储功能（<see cref="SpaceInfoStore"/>）的新实例
        /// </summary>
        /// <param name="provider">服务提供者</param>
        public ProductCaseStore(IServiceProvider provider)
        {
            this.ServiceProvider = provider;
        }

        #region 依赖属性
        protected IServiceProvider ServiceProvider { get; }

        /// <summary>
        /// 获取 事件总线
        /// </summary>
        protected IEventBus EventBus => ServiceProvider.GetService<IEventBus>();

        /// <summary>
        /// 获取 日志对象
        /// </summary>
        protected ILogger Logger => ServiceProvider.GetLogger(GetType());

        /// <summary>
        /// 获取 实体仓储模型
        /// </summary>
        protected IRepository<Entity, Guid> EntityRepository => ServiceProvider.GetService<IRepository<Entity, Guid>>();

        #endregion

        #region 查/增/改/删
        /// <summary>
        /// 获取 实体查询数据集
        /// </summary>
        public virtual IQueryable<Entity> Entities => EntityRepository.QueryAsNoTracking();

        /// <summary>
        /// 新增
        /// </summary>
        public OperationResult Insert(params Entity[] entities)
        {
            Check.NotNull(entities, nameof(entities));

            var operation = EntityRepository.Insert(entities);
            if (operation.Succeeded)
            {
                //触发事件
                EntityEventData<Entity> eventData = new(EntityRepository.DbContext, OperateType.Insert) { Entities = entities.ToList() };
                EventBus?.Publish(eventData);
            }
            return operation;
        }

        /// <summary>
        /// 异步新增
        /// </summary>
        public async Task<OperationResult> InsertAsync(params Entity[] entities)
        {
            Check.NotNull(entities, nameof(entities));

            var result = await EntityRepository.InsertAsync(entities);
            if (result.Succeeded)
            {
                //触发事件
                EntityEventData<Entity> eventData = new(EntityRepository.DbContext, OperateType.Insert) { Entities = entities.ToList() };
                await EventBus?.PublishAsync(eventData);
            }
            return result;
        }

        /// <summary>
        /// 更新
        /// </summary>
        public OperationResult Update(params Entity[] entities)
        {
            Check.NotNull(entities, nameof(entities));

            var operation = EntityRepository.Update(entities);
            if (operation.Succeeded)
            {
                //触发事件
                EntityEventData<Entity> eventData = new(EntityRepository.DbContext, OperateType.Update) { Entities = entities.ToList() };
                EventBus?.Publish(eventData);
            }
            return operation;
        }

        /// <summary>
        /// 异步更新
        /// </summary>
        public async Task<OperationResult> UpdateAsync(params Entity[] entities)
        {
            Check.NotNull(entities, nameof(entities));

            var operation = OperationResult.Success();
            EntityEventData<Entity> eventData = new(EntityRepository.DbContext, OperateType.Update);

            foreach (var entity in entities)
            {
                Check.NotEmpty(entity.Id, nameof(entity.Id));
                var e = await EntityRepository.GetAsync(entity.Id);
                if (e == null)
                {
                    return new OperationResult(OperationResultType.Forbidden, $"编号为“{entity.Id}”的 {nameof(entity)} 不存在。");
                }
                operation = await EntityRepository.UpdateAsync(entity);
                if (!operation.Succeeded)
                {
                    return operation;
                }
                eventData.Entities.Add(entity);
            }

            if (eventData.HasData())
            {
                await EventBus?.PublishAsync(eventData);
            }
            return operation;
        }

        /// <summary>
        /// 删除
        /// </summary>
        public OperationResult Delete(params Entity[] entities)
        {
            Check.NotNull(entities, nameof(entities));

            var result = EntityRepository.Delete(entities);
            if (result.Succeeded)
            {
                //触发事件
                EntityEventData<Entity> eventData = new(EntityRepository.DbContext, OperateType.Delete) { Entities = entities.ToList() };
                EventBus?.Publish(eventData);
            }
            return result;
        }

        /// <summary>
        /// 异步删除
        /// </summary>
        public async Task<OperationResult> DeleteAsync(Guid[] ids)
        {
            Check.NotNull(ids, nameof(ids));

            var operation = OperationResult.Success();
            EntityEventData<Entity> eventData = new(EntityRepository.DbContext, OperateType.Delete);

            foreach (var id in ids)
            {
                Check.NotEmpty(id, nameof(id));

                var entity = EntityRepository.Get(id);
                if (entity == null)
                {
                    return new OperationResult(OperationResultType.Forbidden, $"编号为“{id}”的 {nameof(entity)} 不存在。");
                }
                operation = await EntityRepository.DeleteAsync(entity);
                if (!operation.Succeeded)
                {
                    return operation;
                }
                eventData.Entities.Add(entity);
            }
            if (eventData.HasData())
            {
                await EventBus?.PublishAsync(eventData);
            }
            return operation;
        }

        #endregion

        #region Dto相关
        /// <summary>
        /// 异步以DTO为载体新增
        /// </summary>
        /// <param name="dtos">DTO信息</param>
        /// <returns>业务操作结果</returns>
        public virtual async Task<OperationResult> InsertByDtoAsync(params InputDto[] dtos)
        {
            Check.NotNull(dtos, nameof(dtos));
            Check.Validate<InputDto, Guid>(dtos, nameof(dtos));

            EntityEventData<Entity> eventData = new(EntityRepository.DbContext, OperateType.Insert);
            OperationResult result = await EntityRepository.InsertAsync(dtos, updateFunc:
              async (dto, entity) =>
              {
                  eventData.Entities.Add(entity);
                  return await Task.FromResult(entity);
              });

            if (result.Succeeded)
            {
                if (eventData.HasData())
                {
                    await EventBus?.PublishAsync(eventData);
                }
            }
            return result;
        }

        /// <summary>
        /// 异步以DTO为载体新增
        /// </summary>
        /// <param name="dtos">DTO信息</param>
        /// <returns>业务操作结果</returns>
        public virtual async Task<OperationResult> UpdateByDtoAsync(params InputDto[] dtos)
        {
            Check.NotNull(dtos, nameof(dtos));
            Check.Validate<InputDto, Guid>(dtos, nameof(dtos));

            EntityEventData<Entity> eventData = new(EntityRepository.DbContext, OperateType.Update);
            OperationResult result = await EntityRepository.UpdateAsync(dtos, updateFunc:
             async (dto, entity) =>
             {
                 eventData.Entities.Add(entity);
                 return await Task.FromResult(entity);
             });

            if (result.Succeeded)
            {
                if (eventData.HasData())
                {
                    await EventBus?.PublishAsync(eventData);
                }
            }
            return result;
        }

        #endregion
    }
}
